package com.zqq.base.livedatabus

import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer

/**
 * 反射的LiveDataBus  https://blog.csdn.net/weixin_41648633/article/details/149605786?spm=1001.2014.3001.5501
 * 用于页面之间通信
 */
object LiveDataBus {
    private val bus = mutableMapOf<String, BusMutableLiveData<Any>>()

    fun <T> with(key: String): BusMutableLiveData<T> {
        if (!bus.contains(key)) {
            bus[key] = BusMutableLiveData()
        }
        return bus[key] as BusMutableLiveData<T>
    }

}

open class BusMutableLiveData<T> : MutableLiveData<T>() {

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, observer)
        hook(observer)
    }

    private fun hook(observer: Observer<in T>) {
        try {
            // 获取LiveData的mObservers字段
            val liveData = LiveData::class.java
            val mObserversField = liveData.getDeclaredField("mObservers") //     private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();  放observer的map
            mObserversField.isAccessible = true

            //获取当前LiveData实例的mObservers映射
            val mObservers = mObserversField.get(this)
            val getMethod = mObservers.javaClass.getDeclaredMethod("get", Any::class.java)
            getMethod.isAccessible = true

            // 获取ObserverWrapper对象
            val entry = getMethod.invoke(mObservers, observer)  //从mObservers 键值对列表中   根据key：observer  获取到 键值对对象 key:Observer<? super T>, value：ObserverWrapper
            var observerWrapper: Any? = null
            if (entry != null && entry is Map.Entry<*, *>) {
                observerWrapper = entry.value
            }

            // 修改mLastVersion与mVersion同步
            if (observerWrapper != null) {  //获取到了 observerWrapper
                val wrapperClass = observerWrapper.javaClass.superclass
                val mLastVersionField = wrapperClass.getDeclaredField("mLastVersion")
                mLastVersionField.isAccessible = true
                val mVersionField = liveData.getDeclaredField("mVersion")
                mVersionField.isAccessible = true
                mLastVersionField.set(observerWrapper, mVersionField.get(this))
            }

        } catch (e: Exception) {
        }
    }
}